#ifndef _PARSE_TOKEN_IMPL
#define _PARSE_TOKEN_IMPL

#include "Parse_token.h"

using namespace parse_token;

/* implement parse_token::Token
	class Err_input {};		// exception		

	mylib::Buffer *in_str;	// the input stream
	std::string lexeme;
	Parse_token token_type;
*/

#include "Algorithm.h"

Parse_token Token::get() {
	if( !in_str )			//
		return Token::token_type;
token_get_token :
	char c;
	if( !in_str->get(c) ) {
		lexeme.clear();
		token_type = parse_token::End;
		return token_type;
	}
	switch(c)  {
	case '/' :	{			// comments
		char ch;
		if( !in_str->get(ch) ) {			// get the next char
			in_str->ret();
			lexeme.clear();
			token_type = parse_token::Undef;
			return token_type;
		}
		switch(ch) {
		case '/' :					// comment
			mylib::skip_line_com(*in_str);	// skip comment
			goto token_get_token;
			break;
		case '*' :
			try {
				mylib::skip_dou_lines_com(*in_str);
			} catch(...) {
				throw Err_input();
			}
			goto token_get_token;
		default:
			in_str->ret(2);			// don't skip it
			lexeme.clear();
			token_type = parse_token::Undef;
			break;
		}		}
	case '%' : {
		char ch;
		if( !in_str->get(ch) ) {			// get the next char
			in_str->ret();
			lexeme.clear();
			token_type = parse_token::Undef;
			return token_type;
		}
		switch(ch) {
		case '%' :
			lexeme = "%%";
			token_type = parse_token::Par_sym;
			break;
		case '{' :
			lexeme = "%{";
			token_type = parse_token::Ucode_start;
			break;
		case '}' :
			lexeme = "%}";
			token_type = parse_token::Ucode_end;
			break;
		default :
			in_str->ret(2);			// don't skip it
			lexeme.clear();
			token_type = parse_token::Undef;
			break;
		}
		break;
			   }
	case ':' : {
		char ch;
		if( !in_str->get(ch) ) {
			in_str->ret();
			lexeme.clear();
			token_type = parse_token::Undef;
			return token_type;
		} else if( ch == '{' ) {
			lexeme = ":{";
			token_type = parse_token::Item_start;
		} else {
			in_str->ret(2);
			lexeme.clear();
			token_type = parse_token::Undef;
		}
		break;   }
	case '}' :
		lexeme = "}";
		token_type = parse_token::Rig_big;
		break;
	case '{' :
		lexeme = "{";
		token_type = parse_token::Lef_big;
		break;
	default: {
		bool end=false;
		if( isspace(c) ) {
			char ch;
			do { if( !in_str->get(ch) ) { end=true; break; }
			} while( isspace(ch) );
			if( !end )
				in_str->ret();
			goto token_get_token;
		} else if( isalpha(c) || c == '_') {	// id
			token_type = parse_token::ID;
			lexeme.clear();
			do {
				lexeme += c;
				if( !in_str->get(c) ) { end=true; break; }
			} while( isalnum(c) || c == '_' );
			if( !end )
				in_str->ret();
			if( lexeme == "RETURN_TYPE" )
				token_type = parse_token::RETURN_TYPE;
			else if( lexeme == "END_ACTION" )
				token_type = parse_token::END_ACTION;
		} else {
			in_str->ret();
			lexeme.clear();
			token_type = parse_token::Undef;
		}
		break;	}
	}
	return token_type;
}
#endif
